import { useRef, useState } from 'react'
import clsx from 'clsx'

type Props = {
  children: React.ReactNode
  actions: React.ReactNode
  actionWidth?: number // px
  className?: string
}

// Minimal swipe-to-reveal container. Horizontal swipe left reveals trailing actions.
export const SwipeableItem = ({ children, actions, actionWidth = 120, className }: Props) => {
  const [offset, setOffset] = useState(0)
  const [open, setOpen] = useState(false)
  const startXRef = useRef<number | null>(null)
  const startYRef = useRef<number | null>(null)
  const movedRef = useRef(false)
  const isSwipingRef = useRef(false)

  const clamp = (val: number) => Math.min(0, Math.max(-actionWidth, val))

  const onTouchStart: React.TouchEventHandler<HTMLDivElement> = (e) => {
    startXRef.current = e.touches[0].clientX
    startYRef.current = e.touches[0].clientY
    movedRef.current = false
    isSwipingRef.current = false
  }
  const onTouchMove: React.TouchEventHandler<HTMLDivElement> = (e) => {
    if (startXRef.current == null) return
    const currentX = e.touches[0].clientX
    const currentY = e.touches[0].clientY
    const dx = currentX - startXRef.current
    const dy = startYRef.current == null ? 0 : currentY - startYRef.current

    if (!isSwipingRef.current) {
      if (Math.abs(dy) > Math.abs(dx)) {
        // treat as vertical scroll, abort swipe tracking
        startXRef.current = null
        startYRef.current = null
        return
      }
      if (Math.abs(dx) > 6) {
        isSwipingRef.current = true
      }
    }

    if (!isSwipingRef.current) {
      return
    }

    movedRef.current = true
    const baseline = open ? -actionWidth : 0
    const next = clamp(baseline + dx)
    setOffset(next)
  }
  const onTouchEnd: React.TouchEventHandler<HTMLDivElement> = () => {
    if (startXRef.current == null) return
    const threshold = -actionWidth * 0.35
    const shouldOpen = isSwipingRef.current ? offset < threshold : open
    setOpen(shouldOpen)
    setOffset(shouldOpen ? -actionWidth : 0)
    startXRef.current = null
    startYRef.current = null
    isSwipingRef.current = false
    movedRef.current = false
  }
  const onClickCapture: React.MouseEventHandler<HTMLDivElement> = (e) => {
    if (movedRef.current) {
      e.preventDefault()
      e.stopPropagation()
      movedRef.current = false
    }
  }

  return (
    <div className={clsx('relative touch-pan-y', className)}>
      <div className="pointer-events-none absolute inset-y-0 right-0 flex items-stretch" style={{ width: actionWidth }}>
        {actions}
      </div>
      <div
        className="relative will-change-transform"
        style={{ transform: `translateX(${offset}px)`, transition: startXRef.current == null ? 'transform 160ms ease-out' : undefined }}
        onTouchStart={onTouchStart}
        onTouchMove={onTouchMove}
        onTouchEnd={onTouchEnd}
        onClickCapture={onClickCapture}
      >
        <div className="relative" style={{ zIndex: 1 }}>
          {children}
        </div>
      </div>
      <div className="pointer-events-none absolute inset-y-0 right-0 flex items-stretch" style={{ width: actionWidth }}>
        <div className="pointer-events-auto flex items-stretch">
          {actions}
        </div>
      </div>
    </div>
  )
}

export default SwipeableItem
